#include <head.h>

// 获取源文件的大小（字节）
// 创建目标文件
int get_src_file_size_and_create_dest_file(const char *src_file, const char *dest_file);

// 复制源文件内容到目标文件内容中
void cp_src_file_to_dest_file(const char *src_file, const char *dest_file, int offset, int size);

int main(int argc, char const *argv[])
{
    if (3 != argc)
    {
        printf("Usage : %s src_file dest_file\n", argv[0]);
        return -1;
    }

    int size = 0;
    size = get_src_file_size_and_create_dest_file(argv[1], argv[2]);

    // 创建进程
    pid_t pid = 0;
    if (-1 == (pid = fork()))
    {
        perror("fork error");
        return -1;
    }
    else if (0 == pid)
    { // 子进程
        cp_src_file_to_dest_file(argv[1], argv[2], 0, size / 2);
        sleep(5); // 等待1秒，保证父进程先执行
        exit(0); // 子进程完成任务后正常退出
    }
    else if (0 < pid)
    { // 父进程
        int status;
        pid_t terminated_pid = waitpid(pid, &status, 0); // 父进程立即等待子进程结束
        if (terminated_pid == pid)
        {
            if (WIFEXITED(status))
            {
                printf("子进程退出码：%d\n", WEXITSTATUS(status));
            }
            else if (WIFSIGNALED(status))
            {
                printf("子进程被信号终止，信号编号：%d\n", WTERMSIG(status));
            }
        }
        else
        {
            perror("waitpid");
        }
        cp_src_file_to_dest_file(argv[1], argv[2], size / 2, size - size / 2);
    }

    return 0;
}

int get_src_file_size_and_create_dest_file(const char *src_file, const char *dest_file)
{
    // 获取源文件的大小（字节）
    int src_fd = open(src_file, O_RDONLY);

    if (-1 == src_fd)
    {
        perror("open error");
        return -1;
    }

    int size = lseek(src_fd, 0, SEEK_END);

    close(src_fd);

    // 创建目标文件

    int dest_fd = open(dest_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);

    if (-1 == dest_fd)
    {
        perror("open error");
        return -1;
    }

    close(dest_fd);

    return size;
}

void cp_src_file_to_dest_file(const char *src_file, const char *dest_file, int offset, int size)
{
    int src_fd = 0;

    int dest_fd = 0;

    // 打开源文件
    if (-1 == (src_fd = open(src_file, O_RDONLY)))
    {
        perror("open error");
        exit(-1);
    }
    // 打开目标文件
    if (-1 == (dest_fd = open(dest_file, O_WRONLY)))
    {
        perror("open error");
        exit(-1);
    }

    // 定位光标
    lseek(src_fd, offset, SEEK_SET);

    lseek(dest_fd, offset, SEEK_SET);

    int ret = 0;
    int num = 0;
    char buf[64] = {0};

    while (true)
    {
        ret = read(src_fd, buf, sizeof(buf));

        if (0 == ret)
        {
            break;
        }

        num += ret;

        if (num > size)
        {
            write(dest_fd, buf, size - (num - ret));
            break;
        }

        write(dest_fd, buf, ret);
    }
    // 关闭文件
    close(src_fd);

    close(dest_fd);
}
